package org.dr.st_docker.aop.aspectj.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.dr.st_docker.aop.aspectj.check.RoleVerifier;
import org.dr.st_docker.aop.aspectj.check.RoleVerifierImpl;
import org.dr.st_docker.aop.aspectj.pojo.Role;


@Aspect
public class RoleAspect {
    @Pointcut("execution(* org.dr.st_docker.aop.aspectj.service.RoleServiceImpl.printRole(..))")
    public void print(){

    }
 /**
  * @DeclareParents：目标代理类上添加新的方法
  * 也就是在RoleServiceImpl类上添加RoleVerifier接口的实现类RoleVerifierImpl
  * defaultImpl：代表默认实现类
  */
    @DeclareParents(value = "org.dr.st_docker.aop.aspectj.service.RoleServiceImpl+",defaultImpl = RoleVerifierImpl.class)
    public RoleVerifier roleVerifier;

    /**
     * args(role, sort)：表示方法的参数列表必须包含两个参数role 和 sort。
     * args 关键字用来指定方法的参数列表。
     */
    @Before("print()&& args(role,sort)")
    public void before(Role role, int sort){
        System.out.println("Before方法执行：首先打印Role对象\n"+role.toString()+"\n然后打印整型排序数sort："+sort+"\n");
    }

    /**
     * After：只要目标执行成功，就被触发，无所谓是成功还是抛出异常
     */
    @After("print()")
    public void after(){
        System.out.println("After方法执行......");
    }

    /**
     *AfterReturning只有当目标成功执行并返回结果后才会触发
     */
    @AfterReturning("print()")
    public void afterReturning(){
        System.out.println("AfterReturning方法执行......");
    }

    /**
     * AfterThrowing只有当目标执行抛出异常时才会触发
     */
    @AfterThrowing("print()")
    public void afterThrowing(){
        System.out.println("AfterThrowing方法执行......");
    }

    /**
     * @param proceedingJoinPoint 反射连接点方法
     *  @Around：可以同时实现前置通知和后置通知
     *  在 around 通知中，你可以通过调用 proceed() 来决定何时执行目标方法。
     *  throwable.printStackTrace()当捕获到异常时，打印异常堆栈跟踪信息到标准错误输出
     */
    @Around("print()")
    public void around(ProceedingJoinPoint proceedingJoinPoint){
        System.out.println("Around方法执行前......");
        try {
            proceedingJoinPoint.proceed();
        }catch (Throwable throwable){
            throwable.printStackTrace();
        }
        System.out.println("Around方法执行后......");
    }
}


/**
 * @Aspect：定义切面
 * @Before：前置通知
 * 创建切面，不引入切点，相对来说比较麻烦
 */


// @Aspect
// public class RoleAspect {
//     @Before("execution(* org.dr.st_docker.aspectj.service.RoleServiceImpl.printRole(..))")
//     public void before(){
//         System.out.println("Before方法执行......");
//     }
//
//     @After("execution(* org.dr.st_docker.aspectj.service.RoleServiceImpl.printRole(..))")
//     public void after(){
//         System.out.println("After方法执行......");
//     }
//
//     @AfterReturning("execution(* org.dr.st_docker.aspectj.service.RoleServiceImpl.printRole(..))")
//     public void afterReturning(){
//         System.out.println("AfterReturning方法执行......");
//     }
//     @AfterThrowing("execution(* org.dr.st_docker.aspectj.service.RoleServiceImpl.printRole(..))")
//     public void afterThrowing(){
//         System.out.println("AfterThrowing方法执行......");
//     }
// }